/*
 * esp_discovery.c
 *
 *  Created on: 2018-3-15
 *      Author: Iron
 */
#include "osapi.h"
#include "user_interface.h"
#include "espnow.h"
#include "simple_pair.h"

/*---------------------------------------------------------------------------*/
/* STA & AP use the same tmpkey to encrypt Simple Pair communication */
static u8 tmpkey[16] = {
	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
};

static u8 ex_key[16] = {
	0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88,
	0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00
};

/*---------------------------------------------------------------------------*/
static void ap_simple_pair_status_callback(u8 *sa, u8 status);
static void sta_simple_pair_status_callback(u8 *sa, u8 status);

/*---------------------------------------------------------------------------*/
LOCAL void ICACHE_FLASH_ATTR
show_key(u8 *buf, u8 len)
{
	u8 i;

	for (i = 0; i < len; i++)
		os_printf("%02x,%s", buf[i], (i%16 == 15?"\n":" "));
}

/*---------------------------------------------------------------------------*/
LOCAL void ICACHE_FLASH_ATTR
wifi_scan_done(void *arg, STATUS status)
{
    int ret;

    if (status == OK) {
        struct bss_info *bss_link = (struct bss_info *)arg;
        while (bss_link != NULL) {
			if (bss_link->simple_pair) {
				os_printf("ssid: %s, channel: %d, rssi: %d\n", bss_link->ssid, bss_link->channel, bss_link->rssi);
				os_printf("simple pair: bssid %02x:%02x:%02x:%02x:%02x:%02x Ready!\n",
					bss_link->bssid[0], bss_link->bssid[1], bss_link->bssid[2],
					bss_link->bssid[3], bss_link->bssid[4], bss_link->bssid[5]);

//				simple_pair_set_peer_ref(bss_link->bssid, tmpkey, NULL);
//				ret = simple_pair_sta_start_negotiate();
//				if (ret){
//					os_printf("Simple Pair: STA start NEG Failed\n");
//				}else{
//					os_printf("Simple Pair: STA start NEG OK\n");
//				}

				ret = esp_now_add_peer(bss_link->bssid, ESP_NOW_ROLE_COMBO, 0, NULL, 16);
				os_printf("esp_now_add_peer ret=%d\n", ret);

//				break;
			}
            bss_link = bss_link->next.stqe_next;
        }
    } else {
        os_printf("err, scan status %d\n", status);
    }

	simple_pair_state_reset();
	register_simple_pair_status_cb(ap_simple_pair_status_callback);
	simple_pair_ap_enter_announce_mode();
	os_printf("Simple Pair: AP Enter Announce Mode ...\n");
}

/*---------------------------------------------------------------------------*/
LOCAL void ICACHE_FLASH_ATTR
ap_simple_pair_status_callback(u8 *sa, u8 status)
{
	switch (status) {
	case  SP_ST_AP_FINISH:
		simple_pair_get_peer_ref(NULL, NULL, ex_key); // u8	*peer_mac,	u8	*tmp_key,	u8	*ex_key
		os_printf("Simple Pair: AP FINISH\n");

		/* TODO: Wait STA use the ex-key communicate with AP, for example use ESP-NOW */

		/* if test ok , deinit simple pair */
//		simple_pair_deinit();
		simple_pair_state_reset();
		register_simple_pair_status_cb(ap_simple_pair_status_callback);
		simple_pair_ap_enter_announce_mode();
		break;

	case SP_ST_AP_RECV_NEG:
		/* AP recv a STA's negotiate request */
		os_printf("Simple Pair: Recv STA Negotiate Request\n");

		/* set peer must be called, because the simple pair need to know what peer mac is */
		simple_pair_set_peer_ref(sa, tmpkey, ex_key);

		/* TODO:In this phase, the AP can interaction with Smart Phone,
                   if the Phone agree, call start_neg or refuse */
		simple_pair_ap_start_negotiate();
		//simple_pair_ap_refuse_negotiate();
		/* TODO:if refuse, maybe call simple_pair_deinit() to ending the simple pair */
		break;

	case SP_ST_WAIT_TIMEOUT:
		/* In negotiate, timeout , so re-enter in to announce mode*/
		os_printf("Simple Pair: Neg Timeout\n");
		simple_pair_state_reset();
		simple_pair_ap_enter_announce_mode();
		break;

	case SP_ST_SEND_ERROR:
		os_printf("Simple Pair: Send Error\n");
		/* maybe the simple_pair_set_peer_ref() haven't called, it send to a wrong mac address */

		break;

	case SP_ST_KEY_INSTALL_ERR:
		os_printf("Simple Pair: Key Install Error\n");
		/* 1. maybe something argument error.
 		   2. maybe the key number is full in system*/

		/* TODO: Check other modules which use lots of keys
                         Example: ESPNOW and STA/AP use lots of keys */
		break;

	case SP_ST_KEY_OVERLAP_ERR:
		os_printf("Simple Pair: Key Overlap Error\n");
		/* 1. maybe something argument error.
 		   2. maybe the MAC Address is already use in ESP-NOW or other module
		      the same MAC Address has multi key*/

		/* TODO: Check if the same MAC Address used already,
                         Example: del MAC item of ESPNOW or other module */
		break;

	case SP_ST_OP_ERROR:
		os_printf("Simple Pair: Operation Order Error\n");
		/* 1. maybe the function call order has something wrong */

		/* TODO: Adjust your function call order */
		break;

	default:
		os_printf("Simple Pair: Unknown Error\n");
		break;
	}
}

LOCAL void ICACHE_FLASH_ATTR
sta_simple_pair_status_callback(u8 *sa, u8 status)
{
	switch (status) {
	case  SP_ST_STA_FINISH:
		simple_pair_get_peer_ref(NULL, NULL, ex_key);
		os_printf("Simple Pair: STA FINISH, Ex_key ");
		show_key(ex_key, 16);
		/* TODO: Try to use the ex-key communicate with AP, for example use ESP-NOW */

		/* if test ok , deinit simple pair */
//		simple_pair_deinit();
		simple_pair_state_reset();
		register_simple_pair_status_cb(ap_simple_pair_status_callback);
		simple_pair_ap_enter_announce_mode();
		os_printf("Simple Pair: AP Enter Announce Mode ...\n");
		break;

	case SP_ST_STA_AP_REFUSE_NEG:
		/* AP refuse , so try simple pair again  or scan other ap*/
		os_printf("Simple Pair: Recv AP Refuse\n");
		simple_pair_sta_enter_scan_mode();
		wifi_station_scan(NULL, wifi_scan_done);
		break;

	case SP_ST_WAIT_TIMEOUT:
		/* In negotiate, timeout , so try simple pair again */
		os_printf("Simple Pair: Neg Timeout\n");
		simple_pair_state_reset();
		simple_pair_sta_enter_scan_mode();
		wifi_station_scan(NULL, wifi_scan_done);
		break;

	case SP_ST_SEND_ERROR:
		os_printf("Simple Pair: Send Error\n");
		/* maybe the simple_pair_set_peer_ref() haven't called, it send to a wrong mac address */
		break;

	case SP_ST_KEY_INSTALL_ERR:
		os_printf("Simple Pair: Key Install Error\n");
		/* 1. maybe something argument error.
 		   2. maybe the key number is full in system*/

		/* TODO: Check other modules which use lots of keys
                         Example: ESPNOW and STA/AP use lots of keys */
		break;

	case SP_ST_KEY_OVERLAP_ERR:
		os_printf("Simple Pair: Key Overlap Error\n");
		/* 1. maybe something argument error.
 		   2. maybe the MAC Address is already use in ESP-NOW or other module
		      the same MAC Address has multi key*/

		/* TODO: Check if the same MAC Address used already,
                         Example: del MAC item of ESPNOW or other module */
		break;

	case SP_ST_OP_ERROR:
		os_printf("Simple Pair: Operation Order Error\n");
		/* 1. maybe the function call order has something wrong */

		/* TODO: Adjust your function call order */
		break;

	default:
		os_printf("Simple Pair: Unknown Error\n");
		break;
	}
}

/*---------------------------------------------------------------------------*/
void ICACHE_FLASH_ATTR
esp_discovery(void)
{
	int ret;

	ret = simple_pair_init();
	if (ret) {
		os_printf("Simple Pair: init error, %d\n", ret);
		return;
	}

	ret = register_simple_pair_status_cb(sta_simple_pair_status_callback);
	if (ret) {
		os_printf("Simple Pair: register status cb error, %d\n", ret);
		return;
	}

	os_printf("Simple Pair: STA Enter Scan Mode ...\n");
	ret = simple_pair_sta_enter_scan_mode();
	if (ret) {
		os_printf("Simple Pair: STA Enter Scan Mode Error, %d\n", ret);
		return;
	}

	/* scan ap to searh which ap is ready to simple pair */
	os_printf("Simple Pair: STA Scan AP ...\n");
	ret = wifi_station_scan(NULL, wifi_scan_done);
	if(!ret){
		os_printf("wifi_station_scan error, ret=%d\n", ret);
	}
}
